﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using JuniperScanner.Core;

namespace JuniperScanner
{
    public partial class FmJuniperScanner : Form
    {
        #region Fields

        private JuniperManager _juniperManager;
        private ScannerSetting _scannerSetting;
        private readonly Bitmap OkImg = JuniperScanner.Properties.Resources.ok;
        private readonly Bitmap ErrorImg = JuniperScanner.Properties.Resources.warning;

        #endregion Fields

        #region Constructors

        public FmJuniperScanner()
        {
            this.InitializeComponent();
            this.InitializeMembers();
        }

        #endregion Constructors

        #region Methods

        private void InitializeMembers()
        {
            this.btnStop.Enabled = false;
            this.bgWorker.DoWork += this.BgWorkerDoWork;
            this.bgWorker.RunWorkerCompleted += this.BgWorkerRunWorkerCompleted;
            this.bgWorker.WorkerReportsProgress = true;
            this.bgWorker.WorkerSupportsCancellation = true;
        }

        private void ActivateStatusLabel(bool active)
        {
            if (active)
            {
                this.statusLabel.Text = "Scanning...";
                this.statusLabel.ForeColor = Color.Red;
            }
            else
            {
                this.statusLabel.Text = "Ready";
                this.statusLabel.ForeColor = Color.Black;
            }
        }

        private string GetBaseUrl()
        {
            var result = this.tbUrl.Text.Trim();

            if (!(result.Contains("http") || result.Contains("https")))
            {
                result = String.Format("{0}{1}", "http://", result);
            }

            if (!result[result.Length - 1].Equals('/'))
            {
                result = String.Format("{0}{1}", result, '/');
            }

            return result;
        }

        private void ExportScanningResults()
        {
            if (JuniperManager.ResponseDetails == null)
            {
                MessageBox.Show("There are nothing to export!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            using (var dialog = new SaveFileDialog())
            {
                dialog.Filter = "Text Files (*.txt)|*.txt";

                if (dialog.ShowDialog(this).Equals(DialogResult.OK))
                {
                    File.AppendAllText(dialog.FileName, JuniperManager.GetResultForExport());
                    MessageBox.Show("Results have been successfully exported!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void DisableControls(Control.ControlCollection controls, bool state)
        {
            foreach (Control control in controls) 
            {
                if (control is GroupBox) 
                {
                    this.DisableControls(control.Controls, state);
                }

                else if (!((Control)control).Name.Equals("btnStop") &&
                    !(control is StatusStrip))
                {
                    ((Control)control).Enabled = state;
                }
                
            }
            this.btnStop.Enabled = !state;
        }

        private bool AtLeastOneCheckSelected() 
        {
            var result = false;

            foreach (var control in this.gbChecks.Controls) 
            {
                if (control is CheckBox && ((CheckBox)control).Checked) 
                {
                    result = true;
                    break;
                }
            }

            return result;
        }

        private void SetResponseSummary() 
        {
            if (this.chbAdminAccess.Checked)
                this.pbAdminAccess.Image = JuniperManager.ResponseSummary.AdminAccessOk ? this.OkImg : this.ErrorImg;
            if (this.chbAuthByPass.Checked)
                this.pbAuthByPass.Image = JuniperManager.ResponseSummary.AuthByPassOk ? this.ErrorImg : this.OkImg;
            if (this.chbMeetingTest.Checked)
                this.pbMeetingTest.Image = JuniperManager.ResponseSummary.MeetingTestOk ? this.ErrorImg : this.OkImg;
            if (this.chbSetupFiles.Checked)
                this.pbSetupFiles.Image = JuniperManager.ResponseSummary.SetupFilesOk ? this.ErrorImg : this.OkImg;
            if (this.chbMultipleSignInPages.Checked)
                this.pbSignInPages.Image = JuniperManager.ResponseSummary.SignInPagesOk ? this.OkImg : this.ErrorImg;
            if (this.chbWebRoot.Checked)
                this.pbWebRoot.Image = JuniperManager.ResponseSummary.WebRootOk ? this.ErrorImg : this.OkImg;
            if (this.chbCheckXss.Checked)
                this.pbXssTest.Image = JuniperManager.ResponseSummary.XssTestOk ? this.OkImg : this.ErrorImg;
        }

        private void ClearResponseSummary() 
        {
            foreach (var control in this.gbResultsSummary.Controls)
            {
                if (control is PictureBox)
                {
                    ((PictureBox)control).Image = null;
                }
            }
        }

        #endregion Methods

        #region Events

        private void BgWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (this._juniperManager != null)
            {
                this.gvResults.DataSource = JuniperManager.ResponseDetails;

                this.DisableControls(this.Controls, true);
                this.ActivateStatusLabel(false);
                this.SetResponseSummary();


                if (JuniperManager.ResponseDetails != null)
                {
                    MessageBox.Show("Scanning completed!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void BgWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            this._juniperManager.CheckResource(this._scannerSetting);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(this.tbUrl.Text))
            {
                MessageBox.Show("You need to enter url!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (!this.AtLeastOneCheckSelected())
            {
                MessageBox.Show("You must select at least one check!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            this.gvResults.DataSource = null;
            this.ClearResponseSummary();
            this._juniperManager = new JuniperManager(this.GetBaseUrl());
            this._scannerSetting = new ScannerSetting
                                     {
                                         MinId = (int)this.nudMin.Value,
                                         MaxId = (int)this.nudMax.Value,
                                         CheckMultipleSignInPages = this.chbMultipleSignInPages.Checked,
                                         CheckWebRoot = this.chbWebRoot.Checked,
                                         CheckSetupFiles = this.chbSetupFiles.Checked,
                                         CheckAuthByPass = this.chbAuthByPass.Checked,
                                         CheckXssVulnerability = this.chbCheckXss.Checked,
                                         CheckAdminAccess = this.chbAdminAccess.Checked,
                                         CheckMeetingTest = this.chbMeetingTest.Checked
                                     };

            this.ActivateStatusLabel(true);
            this.DisableControls(this.Controls, false);
            this.bgWorker.RunWorkerAsync();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            this.bgWorker.CancelAsync();
            MessageBox.Show("Scanning aborted!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.btnStop.Enabled = false;
            this.ActivateStatusLabel(false);
            this.ClearResponseSummary();
            this.gvResults.DataSource = null;
            this._juniperManager.Dispose();
            this._juniperManager = null;
            this.DisableControls(this.Controls, true);
        }

        
        private void btnHelp_Click(object sender, EventArgs e)
        {
            MessageBox.Show("");
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show("CMS SCAN \nContact: Oliver (a) muenchow.ch\n Credits: Dmitry S.");
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            this.ExportScanningResults();
        }

        #endregion Events
    }
}
